package com.yiboshi.rehrs.helper;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.github.benmanes.caffeine.cache.Cache;
import com.yiboshi.rehrs.common.ZhongConfig;
import com.yiboshi.rehrs.domain.entity.ZhongUser;
import com.yiboshi.rehrs.exception.ZhongException;
import com.yiboshi.rehrs.exception.ZyantExceptionUtils;
import com.yiboshi.rehrs.param.ZhongReq;
import com.yiboshi.rehrs.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.TimeUnit;

@Service("HelperZhong_1")
@Slf4j
public class HelperXiaofei extends HelperZhong {

    @Autowired
    ZhongConfigHelper configHelper;

    @Autowired
    RedisHelper redisHelper;


    //pda_id: 351564710852443
    int mode = 1;

    public int getMode() {
        return mode;
    }

    @Override
    protected void deleteVipTokenCache() {
        throw  new RuntimeException("未实现的方法");
    }

    public ZhongConfig getZhongConfig() {
        return configHelper.getConfig(mode);
    }


    static Cache<String, Object> cache = CacheUtils.builder(3600);

    public Map<String,String> logonInit(String account,String imei){
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("type", "init_login");
        jsonObject.put("udid",account);
        jsonObject.put("account",account);
        jsonObject.put("time",System.currentTimeMillis());
        jsonObject.put("imei",imei);
        String format = data_init("account,udid,type,imei,time,dev", jsonObject);
        ZhongReq zhongReq = new ZhongReq();
        zhongReq.setOriginData(format);
        encode(zhongReq);
        JSONObject logon = send(zhongReq, "logon");
        Map<String, String> map = toHeader(logon);
        Map<String, String> meger = meger(map);
        return meger;
    }

    public void backqi5(String account,String qi5uxeel,String imei){
        ZhongReq zhongReq = new ZhongReq();
        String backqi5_string = String.format("account=%s&qi5uxeel=%s&imei=%s&time=%d&dev=", account, qi5uxeel,imei, System.currentTimeMillis());
        log.info("backqi5_string:{}",backqi5_string);
        zhongReq.setOriginData(backqi5_string);
        encode(zhongReq);
        JSONObject backqi5 = send(zhongReq, "backqi5");
        log.info("backqi5 res:{}",backqi5);
    }

//https://211.156.197.65/pdalogin/p/common/noTokenAccessCheckIsPhoneLoginSM4/hKImlNsRNNhd
    public String noTokenAccessCheckIsPhoneLoginSM4(Map<String,String> headers) {
        try{
            HttpResponse httpResponse = HttpClientUtils.doPostProxy("https://211.156.197.65/pdalogin/p/common/noTokenAccessCheckIsPhoneLoginSM4/hKImlNsRNNhd"
                    , headers, IdWorker.get32UUID().getBytes(), null);
            JSONObject jsonObject = HttpClientUtils.toJson(httpResponse);
            if("B00404".equalsIgnoreCase(jsonObject.getString("resCode"))){
                Header[] qi5uxeels = httpResponse.getHeaders("qi5uxeel");
                return qi5uxeels[0].getValue();
            }
        }catch (Exception e){
            log.error("",e);
        }

        return null;
    }

    public Map<String,String> logonThird(ZhongReq zhongReq){
        zhongReq.setType("loginbyusrface");
        Map<String, String> map = toRemoteVipHeader(zhongReq);
        return map;
    }

    public Map<String, String> logonHeader(ZhongReq zhongReq) {

        String account = zhongReq.getAccount();
        //zhongReq.setImei("351564710852443");
        String imei = zhongReq.getImei();
        String time = zhongReq.getTime();
        if (StrUtil.isEmpty(time)) {
            time = (System.currentTimeMillis()) + "";
            zhongReq.setTime(time);
        }
        String key = "logonHeader-init:"+imei+":"+account;
        Map<String, String> map = null;
        Object o = cache.getIfPresent(key);
        if(o==null){ //30分钟
            //1、登录请求init
            Map<String, String> stringMap = logonInit(account, imei);
            ZyantExceptionUtils.x(CollUtil.isEmpty(stringMap),"授权异常，请稍后再试(access)");
            //2、404地址访问
            String qi5uxeel = noTokenAccessCheckIsPhoneLoginSM4(stringMap);
            ZyantExceptionUtils.x(StrUtils.isBlank(qi5uxeel),"授权异常，请稍后再试(access)");
            //3、回传参数
            backqi5(account,qi5uxeel,imei);
            cache.put(key,1);
        }
        //4、登录授权
        map = logonThird(zhongReq);
        if(CollUtil.isEmpty(map)){
            return null;
        }
        //重新签名
        long time_new = System.currentTimeMillis();
        map.put("jdpt_req_time", time_new + "");
        map.put("jdpt_sign", SHA256Util.Jdpt_sign(time_new + "", "", account));
        return map;

    }

    public Map<String, String> toRemoteVipHeader(ZhongReq zhongReq) {
        String account = zhongReq.getAccount();
        String time = zhongReq.getTime();
        if (StrUtil.isEmpty(time)) {
            time = (System.currentTimeMillis()) + "";
            zhongReq.setTime(time);
        }
        JSONObject jsonObject = (JSONObject) JSON.toJSON(zhongReq);
        jsonObject.put("password", "fakepasswd");
        jsonObject.put("udid", account);
        jsonObject.put("time", time);
        jsonObject.put("type", zhongReq.getType());
        String format = data_init("account,password,udid,type,imei,dev,time", jsonObject);
        log.info("人脸登录授权 loginbyusrface logon req {} ",format);
        zhongReq.setOriginData(format);
        //           account=215301150011&password=fakepasswd&udid=215301150011&type=loginbyusrface&imei=351564710852443&dev=&time=1743305617914
        //origin-req=account=215301150011&password=fakepasswd&udid=215301150011&type=loginbyusrface&imei=351564710852443&dev=&time=1743305249186
        encode(zhongReq);
        JSONObject logon_json = send(zhongReq, "logon");

        //缓存用户数据ZhongUserVip
        String u_info_str = Optional.ofNullable(logon_json).map(o -> o.getString("u_info"))
                .orElse(null);
        if (StrUtil.isNotBlank(u_info_str)) {
            ZhongUser zhongUser = new ZhongUser();
            JSONObject jsonObject1 = JSONObject.parseObject(u_info_str);
            zhongUser.setMode(getMode());
            zhongUser.setAccount(account);
            zhongUser.setFullname(jsonObject1.getString("name"));
            zhongUser.setImei(jsonObject1.getString("imei"));
            zhongUser.setPadId(jsonObject1.getString("pad_id"));
            zhongUser.setToken(jsonObject1.getString("token"));
            zhongUser.setVipExpDate(DateUtils.strToLocalDateTime(jsonObject1.getString("vipExpDate")));
            LocalDateTime vipExpDate = zhongUser.getVipExpDate();
            String x_user_key = "z:x-user:" + getMode() + ":" + account;
            redisHelper.save(x_user_key, zhongUser, 60+AperStringUtils.randomNum(40), TimeUnit.MINUTES);
            if (vipExpDate.getYear() > 2020) {
                ThreadPoolUtils.submitTask(()->{
                    zhongUserVipService.saveOrUpdateUser(zhongUser);
                });
            }
        }else{
            log.error("toRemoteVipHeader u_info is null,logon_json:{}",logon_json);
        }

        Map<String, String> map = toLogonHeader(logon_json);
        //合并其他header

        //map = meger(map);
        map.remove("Access-Control-Allow-Origin");
        return map;
    }


    public Map<String, String> vipHeader(ZhongUser zhongSessionUser, ZhongReq zhongReq) {

        //模拟VIP登录 获取VIP token
        ZhongUser cacheVipUser = getVipUserDB(getMode());
        String account = cacheVipUser.getAccount();
        String x_user_key = x_user_key(account);
        ZhongUser zhongUser =  redisHelper.loadByCache(x_user_key,ZhongUser.class);
        if (zhongUser == null) {
            ZhongReq zhongReqVipLogon = new ZhongReq();
            zhongReqVipLogon.setAccount(account);
            zhongReqVipLogon.setImei("351564710852443");
            zhongReqVipLogon.setType("loginbyusrsms");
            this.toRemoteVipHeader(zhongReqVipLogon);
        }
        zhongUser = redisHelper.loadByCache(x_user_key,ZhongUser.class);
        if (zhongUser == null) {
            //
            throw new ZhongException("X300", "用户token错误,请检查");
        }
        String vipToken = zhongUser.getToken();
        String type = zhongReq.getType();
        zhongReq.setToken(vipToken);
        String type_new = getZhongConfig().getOtherMap().get(type);
        type = StrUtil.isNotBlank(type_new) ? type_new : type;
        zhongReq.setType(type);
        zhongReq.setTime(System.currentTimeMillis() + "");
        // 将对象转换为JSONObject
        JSONObject jsonObject = (JSONObject) JSON.toJSON(zhongReq);
        jsonObject.put("pda_user_token",zhongSessionUser.getToken());
        //token=0c862f3ca0340fbcf8688cf556e290e2&pda_user_token=c062b424f2bc4dd2a40ee6b495644a14&type=ticketvalidator&imei=867382035888381&time=1742435305280&dev=
        String format = data_init("token,pda_user_token,type,imei,time,dev", jsonObject);
        zhongReq.setOriginData(format);

        encode(zhongReq);

        JSONObject jsonObjectRes = send(zhongReq, "vip");

        Map<String, String> map = toVipHeader(jsonObjectRes);

        //合并其他header
        Map<String, String> mapRes = new HashMap<>();//configHelper.fiddleMap();
        mapRes.putAll(map);
        mapRes.put("pda_version","244");

        //重新签名
        String Jdpt_req_time = System.currentTimeMillis()+"";
        String Jdpt_sign = SHA256Util.Jdpt_sign(Jdpt_req_time, zhongSessionUser.getToken(), zhongSessionUser.getAccount());
        mapRes.put("jdpt_sign", Jdpt_sign);
        mapRes.put("jdpt_req_time",Jdpt_req_time);
        mapRes.put("person_no", zhongSessionUser.getAccount());
        mapRes.put("pda_user_token", zhongSessionUser.getToken());
        if(Objects.equals(type,"newCallAndFile")){
            mapRes.put("user-agent","okhttp/3.10.0");
            mapRes.put("content-type","application/x-www-form-urlencoded; charset=utf-8");
        }

        return mapRes;
    }

    @Override
    public Map<String, String> channelHeader(String uri, ZhongUser zhongUser) {
        String type = "";
        ZhongReq zhongReq = new ZhongReq();
        zhongReq.setAccount(zhongUser.getAccount());
        zhongReq.setImei(zhongUser.getImei());
        zhongReq.setTime(System.currentTimeMillis()+"");
        if(uri.contains("loginbyusrface")){
            zhongReq.setType("loginbyusrface");
            return this.logonHeader(zhongReq);
        }else  if(uri.contains("findpdasignwaybillinfonew")){
            type = "changenav&symb=0&dev=";
        }else {
            type = uri.substring(uri.lastIndexOf("/") + 1);
        }
        zhongReq.setType(type);
        return this.vipHeader(zhongUser,zhongReq);
    }

    private Map<String, String> toVipHeader(JSONObject jsonObject) {
        Map<String, String> map = toLogonHeader(jsonObject);
        return map;
    }

    private Map<String, String> toLogonHeader(JSONObject jsonObject) {
        Map<String, String> map = toHeader(jsonObject);
        return map;
    }
    public static Map<String, String> toHeader(JSONObject jsonObject) {
        JSONObject z_info = jsonObject.getJSONObject("z_info");
        if (z_info == null) {
            z_info = jsonObject;
        }

        // "pda_version": "244",
        //        "pda_sys_version": "12",
        //        "version_name": "1.4.6",
        //        "dlv_equipment_type": "Newland",
        //        "agent": "Dalvik/2.1.0 (Linux; U; Android 9; Build/PQ3A.190801.002)",
        JSONObject headers = z_info.getJSONObject("headers");
        Map<String, String> end = MapBuilder
                .start("jdpt_req_time", z_info.getString("time"))
                .put("jdpt_sign", z_info.getString("jdpt_sign"))
                .put("pda_id", z_info.getString("pda_id"))
                .put("person_no", z_info.getString("account"))
                .put("version_name", headers.getString("version_name"))
                .put("qi5uxeel", z_info.getJSONObject("qi5uxeel").getString("qi5uxeel"))
                .put("pda_user_token", z_info.getString("pda_user_token"))
                .put("pda_sys_version", z_info.getString("pda_sys_version"))
                .put("pda_version", z_info.getString("pda_version"))
                .put("dlv_equipment_type", headers.getString("dlv_equipment_type"))
                .put("user-agent", headers.getString("agent"))
                .put("pda_id", headers.getString("pda_id"))
                .put("cps-magic", headers.getString("Cps"))
                //.put("requestUnifyCode", z_info.getString("requestUnifyCode"))
                .end();
        if(StrUtils.isBlank(end.get("pda_user_token"))){
            end.remove("pda_user_token");
        }
        //end.put("pda_sys_version",z_info.getString("pda_sys_version"));
        //end.put("pda_version",z_info.getString("pda_version"));
        //end.put("u_user_token",)
        return end;
    }


    public void encode(ZhongReq zhongReq) {
        String originData = zhongReq.getOriginData();
        ZhongConfig zhongConfig = getZhongConfig();
        try {
            String encrypt = MyAESUtil.encrypt(originData, zhongConfig.getAesKeyStr().getBytes(), zhongConfig.getAesIvStr());
            String sign = MyAESUtil.sign(originData, zhongConfig.getSignStr());
            zhongReq.setData(encrypt);
            zhongReq.setSign(sign);
            zhongReq.setCoded(1);
        } catch (Exception e) {
            log.error("", e);
        }

    }

    public JSONObject decode(String dataStr) {
        ZhongConfig zhongConfig = getZhongConfig();
        String decryptAES = MyAESUtil.decryptAES(dataStr,
                getZhongConfig().getAesKeyStr().getBytes(), zhongConfig.getAesIvStr());
        //log.info("decryptAES:{}", decryptAES);
        JSONObject data = null;
        if (decryptAES.startsWith("{")) {
            data = JSONObject.parseObject(decryptAES);
        } else {
            data = new JSONObject();
            data.put("data", data);
        }
        return data;
    }





}
